再寫C#時常會碰到大量字串串接的場景,例如:SQL串接、Json串接、迴圈串字串、等等...,所以想要更了解編譯器底層的優化機制,才不會寫出效能不佳的程式,以下記錄了幾個常遇到的場景。
範例1:
var a = "a" + "b" + "c" + "d";
這個範例在編譯時就能得知a的結果,編譯器會直接合併字串,所以不會有效能上的損耗,如下:
var a = "abcd";
範例2:
var a = "a";
var b = Console.ReadLine(); //input b
a = a + b;
這個範例無法再編譯期得知b的結果,且因字串有不可變更特性,所以第三行的a不會以第一行為基礎加上b,而是一個全新的字串,結果總共會產生三個字串"a", "b", "ab",而不是"b", "ab"。
範例3:
var a = "a";
var b = Console.ReadLine(); //input b
var c = "c";
var d = a + b + c;
這個範例編譯期無法得知結果,且以前學過在整數相加的過程中會由左到右執行,先做a+b然後暫存起來再做+c,所以我想結果應該會產生"a", "b", "c", "ab", "abc",五個字串,那這樣串連很多字串時不是就很恐怖會產生一堆暫存字串,但其實編譯器不會這麼笨XD,編譯器會把+優化成string.Concat,所以結果只會產生"a", "b", "c", "abc",四個字串,如下:
var a = "a";
var b = Console.ReadLine(); //input b
var c = "c";
var d = string.Concat(a, b, c);
範例4:
var a = "";
for (var i = 1; i <= 5; i++)
{
a += i;
}
這個範例會產生"1", "12", "123", "1234", "12345",字串中有大量重複的地方,會造成效能上很大的損耗,所以如果需要在迴圈內串接字串會建議使用StringBuilder來代替+,使用StringBuilder結果就只會產生一個"12345"(不包含i轉成字串),如下:
var a = new StringBuilder("");
for (var i = 1; i <= 5; i++)
{
a.Append(i);
}
範例5:
var a = 1 + "1" + true + DateTime.Now;
這個範例結果會等於所有項目做字串相加,因為在+運算中只要有一個以上的項目是字串,就會轉變為字串相加,遇到非字串的物件,則會使用繼承object的ToString方法做轉型,如下:
var a = string.Concat(new object[] {1 , "1" , true , DateTime.Now});
範例6:
var a = "a";
var b = null;
var c = a + b;
這個範例c的值會等於"a",字串相加時遇到null會以空字串替代,所以b會被替代為空字串。
參考文章:
如何:串連多個字串 (C# 程式設計手冊)
分享一個會讓人精神錯亂的 .NET 觀念 ( 神奇的 + 運算子 )